#include <stdio.h>
#include <wiringPi.h>
#include <wiringPiI2C.h>

#define u16 unsigned int 
#define u8  unsigned char

#define IIC_SDA 8
#define IIC_SCL 9
int CY;

//****************************************
// 定义MPU6050内部地址
//****************************************
#define	SMPLRT_DIV		0x19	//陀螺仪采样率，典型值：0x07(125Hz)
#define	CONFIG			0x1A	//低通滤波频率，典型值：0x06(5Hz)
#define	GYRO_CONFIG		0x1B	//陀螺仪自检及测量范围，典型值：0x18(不自检，2000deg/s)
#define	ACCEL_CONFIG	0x1C	//加速计自检、测量范围及高通滤波频率，典型值：0x01(不自检，2G，5Hz)
#define	ACCEL_XOUT_H	0x3B
#define	ACCEL_XOUT_L	0x3C
#define	ACCEL_YOUT_H	0x3D
#define	ACCEL_YOUT_L	0x3E
#define	ACCEL_ZOUT_H	0x3F
#define	ACCEL_ZOUT_L	0x40
#define	TEMP_OUT_H		0x41
#define	TEMP_OUT_L		0x42
#define	GYRO_XOUT_H		0x43
#define	GYRO_XOUT_L		0x44	
#define	GYRO_YOUT_H		0x45
#define	GYRO_YOUT_L		0x46
#define	GYRO_ZOUT_H		0x47
#define	GYRO_ZOUT_L		0x48
#define	PWR_MGMT_1		0x6B	//电源管理，典型值：0x00(正常启用)
#define	WHO_AM_I		0x75	//IIC地址寄存器(默认数值0x68，只读)
#define	SlaveAddress	0x68	//MPU6050器件地址

// 延时5us
void Delay(){
    delayMicroseconds(5);
}

// SDA 输出  x: 0-输出低 1-输出高
void IIC_SDA_OUT(u8 x){
    pinMode (IIC_SDA, OUTPUT);
    if (x == 1) {
        digitalWrite(IIC_SDA,HIGH);
    }
    else {
        digitalWrite(IIC_SDA,LOW);
    }
}
// SDA 输入  
int IIC_SDA_IN(){
    pinMode(IIC_SDA, INPUT);
    // pullUpDnControl(IIC_SDA, PUD_UP);
    int ret = digitalRead(IIC_SDA);
    return ret;
}

// SCL 输出  x: 0-输出低 1-输出高
void IIC_SCL_OUT(u8 x){
    pinMode (IIC_SCL, OUTPUT);
    if (x == 1) {
        digitalWrite(IIC_SCL,HIGH);
    }
    else {
        digitalWrite(IIC_SCL,LOW);
    }
}

// IIC 开始信号
void I2C_Start(){
    IIC_SDA_OUT(1);
    IIC_SCL_OUT(1);
    Delay();
    IIC_SDA_OUT(0);
    Delay();
    IIC_SCL_OUT(0);
}

// IIC停止
void I2C_Stop(){
    IIC_SDA_OUT(0);
    IIC_SCL_OUT(1);
    Delay();
    IIC_SDA_OUT(1);
    Delay();
}
// 输出 ack=0
void I2C_SendACK(int ack){
    IIC_SDA_OUT(ack);
    IIC_SCL_OUT(1);
    Delay();
    IIC_SCL_OUT(0);
    Delay();
}
// 输出  ack=1
int I2C_RecvACK(){
    IIC_SCL_OUT(1);
    Delay();
    CY = IIC_SDA_IN();
    Delay();
    return CY;
}

// 写一字节数据
void I2C_SendByte(u8 wdata){    
    u8 i;    
    for(i=0;i<8;i++){        
        if(wdata&0x80)     
            IIC_SDA_OUT(1);           
        else     
            IIC_SDA_OUT(0);           
        wdata<<=1;          
        IIC_SCL_OUT(1);          
        Delay();          
        IIC_SCL_OUT(0);    
    }    
    I2C_RecvACK();
}
// 读取一字节数据
u8 I2C_RecvByte(){    
    u8 i,bytedata;    
    IIC_SDA_OUT(1);     
    for(i=0;i<8;i++){        
        bytedata<<=1;
        IIC_SCL_OUT(1);          
        Delay();           
        bytedata |= IIC_SDA_IN();        
        IIC_SCL_OUT(0);        
        Delay();    
    }    
    return bytedata;
}
// 向设备的寄存器地址address 写入数据mdata 
void Single_WriteI2C(u8 address,u8 mdata){    
    I2C_Start();    
    I2C_SendByte(SlaveAddress);    /*设备地址*/    
    I2C_SendByte(address);         /*寄存器地址*/    
    I2C_SendByte(mdata);           /*写数据*/    
    I2C_Stop();
}
// 从设备的指定寄存器 读取数据
u8 Single_ReadI2C(u8 address){  
    u8 rdata;    
    I2C_Start();    
    I2C_SendByte(SlaveAddress);         
    I2C_SendByte(address);      
    I2C_Start();    
    I2C_SendByte(address + 1);        
    rdata=I2C_RecvByte();    
    I2C_SendACK(1);    
    I2C_Stop();    
    return rdata;
}

// 初始化 mpu6050
void initMPU6050(){
    Single_WriteI2C(PWR_MGMT_1, 0x00);	//解除休眠状态
	Single_WriteI2C(SMPLRT_DIV, 0x07);
	Single_WriteI2C(CONFIG, 0x06);
	Single_WriteI2C(GYRO_CONFIG, 0x18);
	Single_WriteI2C(ACCEL_CONFIG, 0x01);
}

int getData(int reg_address){
   return (Single_ReadI2C(reg_address) << 8) + Single_ReadI2C(reg_address + 1);
}


int main (void)
{ 
    wiringPiSetup();
    initMPU6050();
    while(1){
        printf("ACCEL_XOUT_data = %d\n",getData(ACCEL_XOUT_H));
        printf("ACCEL_YOUT_data = %d\n",getData(ACCEL_YOUT_H));
        printf("ACCEL_ZOUT_data = %d\n",getData(ACCEL_ZOUT_H));

        printf("GYRO_XOUT_data = %d\n",getData(GYRO_XOUT_H));
        printf("GYRO_YOUT_data = %d\n",getData(GYRO_YOUT_H));
        printf("GYRO_DOUT_data = %d\n",getData(GYRO_ZOUT_H));

        printf("TEMP_OUT_data = %f\n",((double)getData(TEMP_OUT_H)/340 + 36.53));
        delay(5000);
    }
	return 0 ;
}
